#!/usr/bin/python
# coding=utf-8
import numpy

import cv2
import math
import win32gui
import win32con
import win32api
# import autopy
from PIL import ImageGrab
from PIL import Image
import time
import threading


class QQXuanwuDance():
    def __init__(self):
        # game window handler
        self.g_game_window = 0

        # upper-left corner coordinate of game window
        self.g_game_window_x = 0
        self.g_game_window_y = 0
        self.g_game_rect = 0

        # upper-left corner coordinate of arrows box
        self.g_input_box_x = 0
        self.g_input_box_y = 0
        self.g_input_box_width = 330
        self.g_input_box_height = 44

        # const numbers
        self.k_window_name = u"QQ炫舞"
        # k_window_name = u"微信"
        self.k_input_offset_x = 366
        self.k_input_offset_y = 486

        self.k_arrow_width = 25
        self.k_arrow_height = 25
        # k_arrow_space = 9
        self.k_arrow_space = 10
        self.k_arrow_first_offset_x = 33
        self.k_arrow_first_offset_y = 10
        self.k_max_arrows_count = 8

        # enum of dir
        self.k_dir_up = 0
        self.k_dir_down = 1
        self.k_dir_left = 2
        self.k_dir_right = 3
        self.k_dir_unknown = 4
        self.k_dirs = {'left': 2, 'up': 0, 'right': 3, 'down': 1}

        # color of flag
        self.k_flag_r = 255
        self.k_flag_g = 125
        self.k_flag_b = 90

        # flag pos
        self.start_x = 539
        self.start_y = 464

        self.dest_x = 652
        self.dest_y = 464

        self.check_offset = 100

        self.is_in_turn = True

    def getGameWindow(self):
        print('getGameWindow')

        wind = win32gui.FindWindow(None, self.k_window_name)
        return wind

    '''
    初始化 参数值
    '''

    def initSettings(self):

        # get window handle
        g_game_window = self.getGameWindow()
        if g_game_window == 0:
            print("Please launch game before run this script!")
            return False
        print("Game window handle: " + str(g_game_window))

        # place window to foreground
        win32gui.ShowWindow(g_game_window, win32con.SW_RESTORE)
        win32gui.SetForegroundWindow(g_game_window)

        # get game window aabb box
        g_game_rect = win32gui.GetWindowRect(g_game_window)
        self.g_game_window_x = g_game_rect[0]
        self.g_game_window_y = g_game_rect[1]

        # input box coordinate
        self.g_input_box_x = self.g_game_window_x + self.k_input_offset_x
        self.g_input_box_y = self.g_game_window_y + self.k_input_offset_y
        print("input box coordinate: (" + str(self.g_input_box_x) + "," + str(self.g_input_box_y) + ")")
        return True

    '''
    判断是否是箭头的颜色
    '''

    def isArrowColor(self, colorVal):
        print('colorVal', colorVal)
        if colorVal[2] >= 190 and colorVal[0] < 140:  # blue 210?
            return True
        return False

    '''
    检查箭头数量是否是奇数
    '''

    def isArrowsNumOdd(self, imgInputBox):
        # global g_input_box_x
        # global g_input_box_y

        # for curCheckBoxNum in range(k_max_arrows_count):
        # for eachPt in range()

        isOdd = False
        imgWidth = imgInputBox.size[0]
        imgHeight = imgInputBox.size[1]
        print('imgWidth,imgHeight', imgWidth, imgHeight)
        i = self.isArrowColor(imgInputBox.getpixel((imgWidth / 2, imgHeight / 2)))
        print('i', i)
        if i:
            isOdd = True
        return isOdd

    '''
    获取箭头坐标列表
    '''

    def getArrowsList(self, img, isOdd):
        imgWidth = img.size[0]
        imgHeight = img.size[1]

        length = 0
        loopTimes = int(self.k_max_arrows_count / 2)
        if isOdd:
            length = 1
            loopTimes = loopTimes - 1

        baseCoordX = 0
        # imgHeight+=55
        # imgWidth+=5
        baseCoordY = imgHeight / 2 - self.k_arrow_height / 2
        if isOdd:
            baseCoordX = imgWidth / 2 - self.k_arrow_width / 2 - loopTimes * (self.k_arrow_width + self.k_arrow_space)
        else:
            baseCoordX = imgWidth / 2 - self.k_arrow_space / 2 - (
                        loopTimes - 1) * self.k_arrow_space - loopTimes * self.k_arrow_width

        # baseCoordX = baseCoordX + g_input_box_x
        print('baseCoordX,baseCoordY', baseCoordX, baseCoordY)

        baseCoordX = baseCoordX + self.g_input_box_x + 1  # +1 fix offset
        baseCoordY = baseCoordY + self.g_input_box_y

        arrowsList = []
        for i in range(self.k_max_arrows_count):
            curX = baseCoordX + i * (self.k_arrow_width + self.k_arrow_space)
            curY = baseCoordY
            arrowBox = (curX, curY, curX + self.k_arrow_width - 1, curY + self.k_arrow_height)
            image = ImageGrab.grab(arrowBox)
            image.save("./output/i-" + str(i) + ".png", "png")
            key = self.checkModels("./output/i-" + str(i) + ".png")
            arrowsList.append(key)
        return arrowsList

    '''
    箭头截图
    '''

    def grabArrows(self):
        print('grabArrows')
        inputBox = (self.g_input_box_x, self.g_input_box_y, self.g_input_box_x + self.g_input_box_width,
                    self.g_input_box_y + self.g_input_box_height)
        imgInputBox = ImageGrab.grab(inputBox)
        # imgInputBox.save("./output/inputBox.png","png");

        isOdd = self.isArrowsNumOdd(imgInputBox)
        return self.getArrowsList(imgInputBox, isOdd)


    '''根据相似度进行匹配'''

    def checkModels(self, imgName):
        # 读取目标图片
        target = cv2.imread(imgName)
        # target = cv2.cvtColor(numpy.asarray(imgName),cv2.COLOR_RGB2BGR)
        # target = Image.open(imgName)
        # 读取模板图片
        key = 'left'
        val = 0
        for model in ['left', 'up', 'right', 'down']:
            template = cv2.imread("./models/{}.png".format(model))
            # template = Image.open("./png/1.png")
            # 获得模板图片的高宽尺寸
            theight, twidth = template.shape[:2]
            # 执行模板匹配，采用的匹配方式cv2.TM_SQDIFF_NORMED
            result = cv2.matchTemplate(target, template, cv2.TM_SQDIFF_NORMED)
            # 归一化处理
            cv2.normalize(result, result, 0, 1, cv2.NORM_MINMAX, -1)
            # 寻找矩阵（一维数组当做向量，用Mat定义）中的最大值和最小值的匹配结果及其位置
            min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
            # 匹配值转换为字符串
            # 对于cv2.TM_SQDIFF及cv2.TM_SQDIFF_NORMED方法min_val越趋近与0匹配度越好，匹配位置取min_loc
            # 对于其他方法max_val越趋近于1匹配度越好，匹配位置取max_loc
            if min_val > val:
                key = model
                val = min_val
        print(model)
        return self.k_dirs[model]
        # print('{}匹配度mr:{}'.format(model, min_val))

    '''
    根据图片,检测是哪个方向键
    '''

    def checkDir(self, img):
        '''
            key points coordinate:
            (6,8) 	(18,8)
            (6,17) 	(18,17)
        '''
        print(img)
        self.checkModels(img)
        print('img color', img.getpixel((6, 8)), img.getpixel((18, 8)), img.getpixel((6, 17)))
        if self.isArrowColor(img.getpixel((6, 8))) and self.isArrowColor(img.getpixel((18, 8))):
            print("up")
            return self.k_dir_up
        elif self.isArrowColor(img.getpixel((6, 17))) and self.isArrowColor(img.getpixel((18, 17))):
            print("down")
            return self.k_dir_down
        elif self.isArrowColor(img.getpixel((6, 8))) and self.isArrowColor(img.getpixel((6, 17))):
            print("left")
            return self.k_dir_left
        elif self.isArrowColor(img.getpixel((18, 8))) and self.isArrowColor(img.getpixel((18, 17))):
            print("right")
            return self.k_dir_right

        print("unknown")
        return self.k_dir_unknown

    '''
    根据箭头列表，确定方向键列表
    '''

    def getArrowsKeys(self, arrowsList):
        print("keys -------------------- ")
        keysList = []
        for i in range(len(arrowsList)):
            checkResult = self.checkDir(arrowsList[i])
            if checkResult != self.k_dir_unknown:
                keysList.append(checkResult)
        return keysList

    def pressDirKey(self, keyList):
        for i in range(len(keyList)):
            dir = keyList[i]
            keyCode = 0
            if dir == self.k_dir_up:
                keyCode = 38
            elif dir == self.k_dir_down:
                keyCode = 40
            elif dir == self.k_dir_left:
                keyCode = 37
            elif dir == self.k_dir_right:
                keyCode = 39
            hardwareScanCode = win32api.MapVirtualKey(keyCode, 0)
            win32api.keybd_event(keyCode, hardwareScanCode, 0, 0)
            win32api.keybd_event(keyCode, hardwareScanCode, win32con.KEYEVENTF_KEYUP, 0)

    def pressSpaceKey(self):
        keyCode = 32
        hardwareScanCode = win32api.MapVirtualKey(keyCode, 0)
        win32api.keybd_event(keyCode, hardwareScanCode, 0, 0)
        win32api.keybd_event(keyCode, hardwareScanCode, win32con.KEYEVENTF_KEYUP, 0)

    '''
    检测是否是 flag 节奏标 的 颜色
    '''

    def isFlagColor(self, colorVal):
        # for i in range(len(colorVal)):
        # print colorVal[i];
        # if colorVal[0] == k_flag_r and colorVal[1] == k_flag_g and colorVal[2] == k_flag_b:

        # if colorVal[0] < 255:
        if colorVal[0] < 240:
            return False
        if colorVal[1] <= 90 or colorVal[1] >= 120:
            return False
        if colorVal[2] <= 50 or colorVal[2] >= 85:
            return False
        return True

    def startTurn(self, ):
        print("start turn")
        self.is_in_turn = True
        arrowsList = self.grabArrows()
        keyList = self.getArrowsKeys(arrowsList)
        self.pressDirKey(keyList)

    def endTurn(self, ):
        print("end turn")
        self.is_in_turn = False

    def triggerSpace(self):
        print("trigger space")
        self.pressSpaceKey()

    '''
    todo 
    检测 什么时候 开始新一轮，什么时候 要按  space 键
    # 并且按下 空格键
    '''

    def checkTimer(self):

        start_x = self.start_x + self.g_game_window_x if self.g_game_window_x else self.start_x
        start_y = self.start_y + self.g_game_window_y if self.g_game_window_y else self.start_y
        dest_x = self.dest_x + self.g_game_window_x if self.g_game_window_x else self.dest_x
        dest_y = self.dest_y + self.g_game_window_y if self.g_game_window_y else self.dest_y
        # start_x = self.start_x + self.g_game_window_x
        # start_y = self.start_y + self.g_game_window_y
        # dest_x = self.dest_x + self.g_game_window_x
        # dest_y = self.dest_y + self.g_game_window_y

        # startBlockImg = ImageGrab.grab((start_x,start_y,start_x + check_offset,start_y + check_offset));
        # startBlockImg.save("./output/check.png","png");

        while True:
            # time.sleep(0.01);
            print("is in turn?" + str(self.is_in_turn))
            # if  self.is_in_turn:
            #     destBlockImg = ImageGrab.grab((dest_x, dest_y, dest_x + self.check_offset, dest_y + self.check_offset))
            #     if self.isFlagColor(destBlockImg.getpixel((1, 3))):
            #         self.triggerSpace()
            #         self.endTurn()
            # else:
            #     startBlockImg = ImageGrab.grab((start_x, start_y, start_x + self.check_offset, start_y + self.check_offset))
            #     if self.isFlagColor(startBlockImg.getpixel((1, 3))):
            #         self.startTurn()

            startBlockImg = ImageGrab.grab((start_x, start_y, start_x + self.check_offset, start_y + self.check_offset))
            self.startTurn()

    def test(self):
        imgInputBox = Image.open('./output/3.png')
        isOdd = self.isArrowsNumOdd(imgInputBox)
        print('isOdd', isOdd)
        self.getArrowsList(imgInputBox, isOdd)
        # self.getArrowsKeys( self.getArrowsList(imgInputBox, isOdd))


def mainFunc():
    XW = QQXuanwuDance()
    if  XW.initSettings():
        XW.checkTimer()
    # XW.checkTimer()
    # XW.test()


# th = threading.Thread(target = checkTimer)
# th.setDaemon(True);
# th.start();
# dealFunc();

if __name__ == '__main__':
    print('AutoDance')
    mainFunc()
    print('AutoDance exit!')
